//Dialog.ts
import {
    createApp,
    createVNode,
    defineComponent,
    h,
    ref,
    onUnmounted,
    Plugin,
    render,
    inject,
    getCurrentInstance
} from "vue";

import ElementPlus, {ElDialog} from "element-plus";
import Dialog from './dialogTemplate.vue'
import type {App, Component, ComputedOptions, MethodOptions} from "vue";
//引入dialog的类型
import type {DialogProps} from "element-plus";

import 'element-plus/dist/index.css';

export const DialogSymbol = Symbol()
export type OverlayType = {
    component: Component<any, any, any, ComputedOptions, MethodOptions>;
    options?: Partial<DialogProps>;
    params?: any;
};


export class OverlayService {
    private _app?: App = undefined
    //overlay的vue实例
    private OverlayInstance!: App;

    // ui库的组件一般都带有动画效果，所以需要维护一个布尔值，来做展示隐藏
    public show = ref<boolean>(true);

    // 组件库的options
    private options: Partial<DialogProps> = {};

    //在open中传递给子组件的参数
    private params: any = {};

    //挂载的dom
    public overlayElement!: Element | null;

    //子组件
    private childrenComponent!: Component<any,
        any,
        any,
        ComputedOptions,
        MethodOptions>;

    //close触发的resolve，先由open创建赋予
    private _resolve: (value?: unknown) => void = () => {
    };

    private _reject: (reason?: any) => void = () => {
    };

    constructor(app: App) {
        this._app = app;
    }

    public open(options: any): Promise<any> {


        //h(MySon, {...props}, slots);
        return new Promise((reslove, reject) => {
            if (!this._app) {
                reject('_app is undefined')
                return;
            }
            this._resolve = reslove;
            this._reject = reject;
            this.childrenComponent = options.component;

            if (!this._app) {
                return;
            }
            const container = document.createElement("div");
            container.id = options.id || 'wg-dialog';
            this.overlayElement = container
            document.body.appendChild(container)

            const wgDialogChildrenRef = ref()
            let that = this
            const vm = h(
                Dialog,
                {
                    //默认在弹窗关闭时销毁子组件
                    destroyOnClose: true,
                    closeOnClickModal: false,
                    customClass: 'wg-dialog',
                    btns: ['ok', 'cannel'],
                    ...options,

                    modelValue: this.show.value,
                    onClose: this.close.bind(this),
                    onOk: function (callback: any) {
                        if (wgDialogChildrenRef.value != null) {
                            wgDialogChildrenRef.value.acceptClick(options.callback).then(res => {
                                that.ok()
                            })
                        }
                    },
                },
                () => {
                    return h('div', null, [h(this.childrenComponent, {
                        ref: wgDialogChildrenRef,
                        id: options.id, ...options.params
                    })])
                }
            );
            vm.appContext = this._app._context
            render(vm, container)
        });
    }

    //弹窗的关闭方法,可以传参触发open的promise下一步
    public close(msg?: any) {
        this.show.value = false;
        this.overlayElement?.remove()
        this.show.value = true;
        if (msg) {
            this._resolve(msg);
        } else {
            this._resolve();
        }
    }

    public ok(callback?: any) {
        this.show.value = false;
        this.overlayElement?.remove()
        this.show.value = true;
        if (callback) {
            this._resolve(callback);
        } else {
            this._resolve();
        }
    }
}

export function useDialog(): OverlayService {
    const wgModal = inject<OverlayService>(DialogSymbol)
    if (!wgModal) {
        throw new Error('No WgDialog provided!')
    }
    return wgModal;
}

//创建一个hooks 好在setup中使用
// export const useDialog = () => {
//   const overlayService = new OverlayService();
//   return {
//     open: overlayService.open.bind(overlayService),
//     close: overlayService.close.bind(overlayService),
//   };
// };
const plugin: Plugin = {
    install(app: App, options?: { [key: string]: any }) {
        const wgModal = new OverlayService(app)
        app.config.globalProperties.$wgDialog = wgModal
        app.provide(DialogSymbol, wgModal)

    }
}
export default plugin;